home *** CD-ROM | disk | FTP | other *** search
- /* This program will print out exercise lines to the display, and
- then check for correct typing.
- */
-
- /* Ported to the Atari-ST by Randy Hosler on May 16, 1992.
- Ported from unix sources, original author unknown.
- Compiled with HSC 1.33 and MiNT libs.
- cc typist.c libm1.a libm.a
- Looks for *.typ files in d:\sozobon\lib\typist\ or current dir.
- ( see find_lesson() )
- */
-
- #include <stdio.h>
- #include <stddef.h>
- #include <string.h>
- #include <memory.h>
- #include <ctype.h>
- #include <time.h>
- #include <osbind.h>
-
- typedef unsigned char BoolType;
- #if !defined(FALSE)
- #define FALSE 0
- #define TRUE 1
- #endif
-
- #if !defined(NULL)
- #define NULL 0
- #endif
-
- #define CLRSCREEN Cconws("\033H\033J")
- #define BEEP Cconout('\007')
-
- #define ASCII_ESC 27
- #define ASCII_BS 8
- #define ASCII_RUBOUT 127
-
- #define STR_SIZE 256
- typedef char StrType[STR_SIZE + 1];
-
- #define MAX_LINES 1500
- char *cached_lines[MAX_LINES];
-
- int linesInLesson;
- int exerciseStart;
- int newStart;
-
- FILE *lesson_file;
- StrType current_line;
-
- mvcur(r,c)
- int r,c;
- {
- Cconout('\033');
- Cconout('Y');
- Cconout(r+040);
- Cconout(c+040);
- }
-
- wait_user() /* Get any response from user before proceeding */
- {
- mvcur(23, 0);
- Cconws("Press any key to continue...");
- Cnecin();
- }
-
- void get_end_line() /* Read end of line, should be smarter... */
- {
- Cnecin();
- }
-
- int cleanup() /* cleanup routine, esp. SIGINT */
- {
- Cconws("\r\n");
- exit(0);
- }
-
- char *git_lesson() /* Ask user for desired lesson */
- {
- static StrType response;
-
- mvcur(0,0);
- Cconws(" Several lessons are available:\r\n");
- Cconws(" Quick QWERTY course (q1 - q5)\r\n");
- Cconws(" Long QWERTY course (r1 - r14)\r\n");
- Cconws(" QWERTY touch typing (t1 - t16)\r\n");
- Cconws(" Yet Another QWERTY (v1 - v20)\r\n");
- Cconws(" QWERTY Review (u1 - u13)\r\n");
- Cconws(" Dvorak touch typing (d1 - d14)\r\n");
- Cconws(" Typing drills (m1 - m11)\r\n");
- Cconws(" Speed drills (s1 - s4)\r\n");
- Cconws(" Calculator keypad (n1 - n3)\r\n");
- mvcur(11,0);
- Cconws(" Press return to exit or else type the desired lesson name: ");
- gets(response);
- if (strlen(response) == 0)
- cleanup();
- return response;
- }
-
- BoolType get_lesson_line() /* Read line of input from user, in canonical mode */
- {
- if (feof(lesson_file))
- return FALSE;
- if (fgets(current_line, STR_SIZE, lesson_file) == NULL)
- current_line[0] = '\0';
- else {
- if (current_line[strlen(current_line) - 1] == '\n')
- current_line[strlen(current_line) - 1] = '\0';
- }
- return TRUE;
- }
-
- BoolType find_lesson(name) /*locate lesson leave file open so next line begins*/
- char *name;
- {
- StrType fullName;
- StrType target;
- StrType response;
- BoolType done = FALSE;
-
- sprintf(fullName, "d:\\sozobon\\lib\\typist\\%c.typ", name[0]);
- sprintf(target, "*%c%s*", toupper(name[0]), &name[1]);
- lesson_file = fopen(fullName, "r");
- if (lesson_file == NULL) {
- sprintf(fullName, "%c.typ", name[0]); /* try current dir */
- lesson_file = fopen(fullName, "r");
- if (lesson_file == NULL) {
- sprintf(response, "Can't open file %s\n", fullName);
- Cconws("\r\n");
- Cconws(response);
- wait_user();
- return FALSE;
- }
- }
- while (!done) {
- if (!get_lesson_line())
- break;
- if (strncmp(current_line, target, 5) == 0)
- done = TRUE;
- }
- if (!done) {
- sprintf(response, "Lesson %s is not available.\n", &name[1]);
- Cconws("\r\n");
- Cconws(response);
- wait_user();
- return FALSE;
- }
- linesInLesson = 0;
- done = FALSE;
- while (!done) {
- if (!get_lesson_line()) {
- done = TRUE;
- break;
- }
- if (current_line[0] == '*') {
- done = TRUE;
- break;
- }
- if (linesInLesson == MAX_LINES) {
- }
- if (cached_lines[linesInLesson] != NULL) {
- free(cached_lines[linesInLesson]);
- cached_lines[linesInLesson] = NULL;
- }
- cached_lines[linesInLesson] = (char *)malloc(strlen(current_line) + 1);
- if (cached_lines[linesInLesson] == NULL) {
- fprintf(stderr, "malloc() failure\n");
- exit(1);
- }
- strcpy(cached_lines[linesInLesson], current_line);
- linesInLesson ++;
- }
- return TRUE;
- }
-
- void get_exercise(startLine, kind, newStart) /*get length and kind of exercise*/
- int startLine;
- char *kind;
- int *newStart;
- {
- char *thisLine;
- int lineLength;
-
- *newStart = startLine;
- *kind = 'I'; /* default... */
- /* Determine end of exercise */
- while (TRUE) {
- if (*newStart >= linesInLesson)
- break; /* done */
-
- thisLine = cached_lines[*newStart];
- lineLength = strlen(thisLine);
- if (thisLine[lineLength - 2] == '\\') { /* expected terminator */
- *kind = thisLine[lineLength - 1];
- thisLine[lineLength - 2] = '\0'; /* remove */
- (*newStart) ++;
- break;
- }
- if (thisLine[lineLength - 1] == '\\') /* compatibility with BASIC */
- thisLine[lineLength - 1] = '\0'; /* also remove */
- (*newStart) ++;
- }
- }
-
- void displaySpeed(totalChars, elapsed, errs) /* show how fast you were */
- int totalChars;
- long elapsed;
- int errs;
- {
- elapsed = elapsed / 200;
- {
- double testTime = (double)elapsed / (double)60.0; /* time in minutes */
- double words = (double)totalChars / 5.0;
- double speed = words / testTime;
- double adjustedSpeed;
- StrType message;
-
- words -= errs;
- adjustedSpeed = words / testTime;
-
- mvcur(19, 19);
- sprintf(message, "raw speed = %f wpm", speed);
- Cconws(message);
- mvcur(20, 19);
- sprintf(message, "adjusted speed = %f wpm", adjustedSpeed);
- Cconws(message);
- mvcur(21, 19);
- sprintf(message, " with %f%s errors",
- (double)100.0 * errs / totalChars, "%");
- Cconws(message);
- wait_user();
- }
- }
-
- void do_drill() /* \D, a drill */
- {
- int tries;
- int errors;
- int totalChars;
- int i, j;
- char *thisLine;
- int thisLength;
- char ch;
- long startTime, endTime;
-
- tries = 0;
- do { /* a try */
- totalChars = 0;
- errors = 0;
- tries ++;
-
- /* display drill pattern */
- for (i = exerciseStart; i < newStart; i ++) {
- mvcur(3 + (i - exerciseStart) * 2, 0);
- Cconws(cached_lines[i]);
- totalChars += strlen(cached_lines[i]) + 1; /* +1 for NULL */
- }
-
- /* run the drill */
- for (i = exerciseStart; i < newStart; i ++) {
- thisLine = cached_lines[i];
- thisLength = strlen(thisLine);
-
- mvcur(4 + (i - exerciseStart) * 2, 0);
- for (j = 0; j < thisLength; j ++) {
- ch = Cnecin();
- if (i == exerciseStart && j == 0)
- startTime = clock(); /* timer doesn't run till first stroke */
- if (ch == ASCII_ESC) {
- CLRSCREEN;
- goto ALL_DONE;
- }
- if (ch != thisLine[j]) {
- Cconout('X');
- BEEP;
- errors ++;
- }
- else
- Cconout(ch);
- }
- get_end_line();
- }
- endTime = clock();
-
- displaySpeed(totalChars, endTime - startTime, errors);
- CLRSCREEN;
- if (errors > 0 && tries < 3) {
- mvcur(0, 0);
- Cconws("Try again...");
- }
- tries ++;
- } while (errors > 0 && tries < 4);
- ALL_DONE:;
- }
-
- void do_para()
- /* P, practice paragraph */
- {
- int i, j;
- char *thisLine;
- int thisLength;
- char ch;
- int totalChars = 0;
- int errors = 0;
- long startTime, endTime;
-
- /* print out practice text */
- for (i = exerciseStart; i < newStart; i ++) {
- mvcur(3 + (i - exerciseStart), 0);
- Cconws(cached_lines[i]);
- totalChars += strlen(cached_lines[i]);
- }
-
- mvcur(3, 0);
- for (i = exerciseStart; i < newStart; i ++) {
- mvcur(3 + (i - exerciseStart), 0);
- thisLine = cached_lines[i];
- thisLength = strlen(thisLine);
- for (j = 0; j < thisLength; j ++) {
- ch = Cnecin();
- if (i == exerciseStart && j == 0)
- startTime = clock(); /* timer doesn't run till first stroke */
- if (ch == ASCII_ESC) {
- CLRSCREEN;
- goto ALL_DONE;
- }
- /* Allow backspace */
- if (j != 0 && (ch == ASCII_BS || ch == ASCII_RUBOUT)) {
- j --;
- mvcur(3 + (i - exerciseStart), j);
- Cconout(thisLine[j]);
- mvcur(3 + (i - exerciseStart), j);
- j --;
- continue; /* but notice that errors accumulate */
- }
- if (ch != thisLine[j]) {
- mvcur(3 + (i - exerciseStart), j);
- Cconout(thisLine[j]);
- errors ++;
- }
- else
- mvcur(3 + (i - exerciseStart), j + 1);
- }
- get_end_line();
- }
- endTime = clock();
-
- displaySpeed(totalChars, endTime - startTime, errors);
- ALL_DONE:;
- }
-
- void do_type()
- /* T, type out a lesson */
- {
- int i;
-
- CLRSCREEN;
- for (i = exerciseStart; i < newStart; i ++) {
- mvcur(1 + (i - exerciseStart), 0);
- Cconws(cached_lines[i]);
- }
- wait_user();
- CLRSCREEN;
- }
-
- void do_instruction()
- /* I, instruction line */
- {
- CLRSCREEN;
- mvcur(0, 0);
- Cconws(cached_lines[exerciseStart]);
- }
-
- void do_clear()
- /* B, clear screen */
- {
- CLRSCREEN;
- mvcur(1, 29);
- Cconws(cached_lines[exerciseStart]);
- wait_user();
- }
-
- void give_lesson()
- /* dance through lesson file */
- {
- char kind;
-
- exerciseStart = 0;
- while (TRUE) {
- get_exercise(exerciseStart, &kind, &newStart);
- switch (kind) {
- case 'B':
- do_clear();
- break;
-
- case 'P':
- do_para();
- break;
-
- case 'T':
- do_type();
- break;
-
- case 'D':
- do_drill();
- break;
-
- case 'I':
- do_instruction();
- break;
-
- default:
- fprintf(stderr, "Unknown exercise near line %d of this lesson\n",
- newStart - 1);
- exit(1);
- break;
- }
- exerciseStart = newStart;
- if (exerciseStart >= linesInLesson)
- break;
- }
- }
-
- int main(argc, argv)
- int argc;
- char *argv[];
- {
- char *lessonName;
- int i;
-
- CLRSCREEN;
-
- for (i = 0; i < MAX_LINES; i ++)
- cached_lines[i] = NULL;
-
- /* Start and format screen. Open and read exercise file.
- Inquire for lesson to run */
- while (TRUE) {
- CLRSCREEN;
- lessonName = git_lesson();
- if (!find_lesson(lessonName))
- continue;
- give_lesson();
- }
- }
-
-